
#include "ResponseWriter.h"
#include "../../loop/LoopService.h"
#include <event2/http.h>
#include <event2/buffer.h>
#include <sstream>
#include <assert.h>

ResponseWriter::ResponseWriter(evhttp_request* r, LoopService* lp)
    : rsp_(r)
    , loop_(lp)
    , chunk_(false)
{
    assert(rsp_ != nullptr);
}

void ResponseWriter::write(HTTPStatus status, const void* data, int size)
{
    assert(chunk_ == false);
    assert(loop_->is_in_loop_thread());
    // set header
    for (auto& kv : header_) {
        evhttp_add_header(evhttp_request_get_output_headers(rsp_),
            kv.first.c_str(), kv.second.c_str());
    }
    evbuffer* evb = evbuffer_new();
    evbuffer_add(evb, data, size);
    evhttp_send_reply(rsp_, (int)status, HTTPStatusString[status].c_str(), evb);
    evbuffer_free(evb);
}

void ResponseWriter::write(HTTPStatus status, const std::string& msg)
{
    write(status, msg.data(), msg.size());
}

void ResponseWriter::write(HTTPStatus status, const std::istream& ios)
{
    std::ostringstream msg;
    msg << ios.rdbuf();
    write(status, msg.str().data(), msg.str().size());
}



void ResponseWriter::write_chunk_begin(HTTPStatus status)
{
    assert(chunk_ == false);
    assert(loop_->is_in_loop_thread());
    chunk_ = true;
    // set header
    for (auto& kv : header_) {
        evhttp_add_header(evhttp_request_get_output_headers(rsp_),
            kv.first.c_str(), kv.second.c_str());
    }
    evhttp_send_reply_start(rsp_, (int)status, HTTPStatusString[status].c_str());
}

void ResponseWriter::write_chunk(const void* data, int size)
{
    assert(chunk_ == true);
    assert(loop_->is_in_loop_thread());
    evbuffer* evb = evbuffer_new();
    evbuffer_add(evb, data, size);
    evhttp_send_reply_chunk(rsp_, evb);
    evbuffer_free(evb);
}

void ResponseWriter::write_chunk(const std::string& msg)
{
    write_chunk(msg.data(), msg.size());
}

void ResponseWriter::write_chunk(const std::istream& ios)
{
    std::stringstream msg;
    msg << ios.rdbuf();
    write_chunk(msg.str().data(), msg.str().size());
}

void ResponseWriter::write_chunk_end()
{
    assert(chunk_ == true);
    assert(loop_->is_in_loop_thread());
    evhttp_send_reply_end(rsp_);
}
